package com.up.vms.domain.vm.service;

import com.up.vms.domain.module.VideoDTO;
import com.up.vms.infrastructure.util.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import com.up.vms.domain.vm.entity.Video;
import com.up.vms.domain.vm.enums.VideoRecommendFlag;
import com.up.vms.domain.vm.enums.VideoStatus;
import com.up.vms.domain.vm.repository.VideoRepository;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
@Slf4j
public class VideoService {

    @Autowired
    private VideoRepository videoRepository;

    public Video save(Video video) {

        Video newInstance = videoRepository.save(video);

        return newInstance;
    }

    public Video getById(Long id) {

        Optional<Video> optional = videoRepository.findById(id);
        if (optional.isPresent()) {
            return optional.get();
        } else {
            return null;
        }
    }

    public Page<Video> findAllByVideoName(VideoDTO videoDTO) {
        Sort sort = new Sort(Sort.Direction.DESC, "created");
        Pageable pageable = PageRequest.of(videoDTO.getPage(), videoDTO.getSize(), sort);

        return videoRepository.findAllByVideoNameLikeAndStatus("%" + videoDTO.getVideoName() + "%", 1, pageable);
    }

    public Page<Video> findAllByRecommendFlag(VideoDTO videoDTO) {
        Sort sort = new Sort(Sort.Direction.DESC, "sorting");
        Pageable pageable = PageRequest.of(videoDTO.getPage(), videoDTO.getSize(), sort);

        return videoRepository.findAllByRecommendFlagAndShowVideoModeAndStatus(VideoRecommendFlag.RECOMMEND.code, VideoStatus.SHOW.code, 1, pageable);
    }



    public Page<Video> findAllByCase(VideoDTO videoDTO) {

        if (CommonUtils.isNull(videoDTO.getSortColumn())) {
            videoDTO.setSortColumn("created");
        }

        Sort sort = new Sort(Sort.Direction.DESC, videoDTO.getSortColumn());
        Pageable pageable = PageRequest.of(videoDTO.getPage(), videoDTO.getSize(), sort);

        Specification<Video> specification = new Specification<Video>() {
            private static final long serialVersionUID = 1L;

            @Override
            public Predicate toPredicate(Root<Video> root, CriteriaQuery<?> query,
                                         CriteriaBuilder criteriaBuilder) {
                List<Predicate> lst = new ArrayList<Predicate>();

                lst.add(criteriaBuilder.equal(root.get("status"), 1));

                if (videoDTO.getVideoName() != null) {
                    lst.add(criteriaBuilder.like(root.get("videoName"), "%" + videoDTO.getVideoName() + "%"));
                }
                if (videoDTO.getShowVideoMode() != null) {
                    lst.add(criteriaBuilder.equal(root.get("showVideoMode"), videoDTO.getShowVideoMode()));
                }
                if (videoDTO.getCategoryId() != null) {
                    lst.add(criteriaBuilder.equal(root.get("categoryId"), videoDTO.getCategoryId()));
                }

                return query.where(lst.toArray(new Predicate[] {})).getRestriction();

            }
        };

        return videoRepository.findAll(specification, pageable);
    }


    public long countByCategoryId(VideoDTO videoDTO) {
        return videoRepository.countByCategoryId(videoDTO.getCategoryId());
    }

    public void addPlayTimes(Long id) {
        videoRepository.updatePlayTimes(id);
    }
}
